/*
 * InputCharacter.cc
 *
 *  Created on: Nov 6, 2012
 *      Author: Zermingore
 */

#include "InputCharacter.hh"

#include "common/stl.h"
#include "globals/keys.h"
#include "globals/engines.h"
#include "constants/default_keys.h"

#include "input/Input.hh"


InputCharacter::InputCharacter()
{
	// is this really a good idea ?
	glfwEnable(GLFW_STICKY_KEYS); // 'always disable STICKY_KEYS when leaving a section' [ex: menu]

	_mouseButtons = 0x0000;
}

InputCharacter::~InputCharacter()
{
}

// rename this && rewrite to enable a smoother quit
void InputCharacter::treatEvent()
{
	#ifdef DEBUG
		if (glfwGetKey(GLFW_KEY_ESC) == GLFW_PRESS || !glfwGetWindowParam(GLFW_OPENED))
			std::exit(0);
	#endif

  	// should get event close && treat it
	// void glfwSetWindowCloseCallback( GLFWwindowclosefun cbfun )
}


void InputCharacter::keyboardCallback(int key, int state)
{
	// NOTE: if (state) is equivalent of testing state == GLFW_PRESS
	// NOTE: unfortunately, we cannot use a switch here (cases require constant expressions)

	if (key == g_key_move_forward && state)
	{
//		moveForward();

		return;
	}

//	if (key == g_key_move_backward && state)
//		return moveBackward();
//
//	if (key == g_key_move_left && state)
//		return moveLeft();
//
//	if (key == g_key_move_right && state)
//		return moveRight();
//
//	if (key == g_key_tilt_left && state)
//		return tiltLeft();
//
//	if (key == g_key_tilt_right && state)
//		return tiltRight();


	#ifdef DEBUG
		if (state)
			std::cout << "unknown key " << key << std::endl;
	#endif

	/* case g_shift_key:
	   if (state) // => GLFW_PRESS
	 */
}


void InputCharacter::mouseButtonsCallback(int button, int state)
{
	switch (button)
	{
//	case GLFW_MOUSE_BUTTON_LEFT:
//		Input::_mouseLeft = (state == GLFW_PRESS);
//		return;

//	case GLFW_MOUSE_BUTTON_RIGHT:
//		_mouseRight = (state == GLFW_PRESS);
//		return;
//
//	case GLFW_MOUSE_BUTTON_MIDDLE:
//		_mouseMiddle = (state == GLFW_PRESS);
//		return;
	}
}


// TODO: consider character footStepSizes / vehicle velocity - acceleration / ...
void InputCharacter::moveForward()
{
    // TODO update Character position (ifdef server...)
    // TODO consider current velocity

    // updating camera position
    g_graphicEngine.moveCamera(0, 0, -1.); // * character footStepForwardSize
}


void InputCharacter::moveBackward()
{
    g_graphicEngine.moveCamera(0, 0, 1.);
}

void InputCharacter::moveLeft()
{
    g_graphicEngine.moveCamera(1., 0, 0);
}

void InputCharacter::moveRight()
{
    g_graphicEngine.moveCamera(-1., 0, 0);
}


void InputCharacter::lookLeft()
{
    g_graphicEngine.turnCamera(0.01, 0, 0);
}

void InputCharacter::lookRight()
{
    g_graphicEngine.turnCamera(-0.01, 0, 0);
}

void InputCharacter::lookDown()
{
    g_graphicEngine.turnCamera(0, -0.01, 0);
}

void InputCharacter::lookUp()
{
    g_graphicEngine.turnCamera(0, 0.01, 0);
}



void InputCharacter::tiltLeft()
{
    // TODO: control management: already tilted => not possible anymore
    // cd implement voluntary side fall
    g_graphicEngine.tiltCamera(-1., 0, 0);
}

void InputCharacter::tiltRight()
{
    g_graphicEngine.tiltCamera(1., 0, 0);
}



// Updates mouse coordinates
void InputCharacter::mousePositionCallback(int x, int y)
{
    if (x != g_oldMouseX)
    {
        if (x > g_oldMouseX)
            lookLeft();
        else
            lookRight();

        g_oldMouseX = x;
    }

    if (y != g_oldMouseY)
    {
        if (y > g_oldMouseY)
            lookDown();
        else
            lookUp();

        g_oldMouseY = y;
    }
}
